package com.institute.service;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.common.util.TreeNode;
import com.institute.dao.InstituteRepository;
import com.institute.dao.PositionRepository;
import com.institute.entity.Institute;
import com.institute.entity.Position;
import com.institute.entity.dto.InstituteDTO;
import com.institute.entity.dto.PrincipalDTO;
import com.staff.dao.StaffRepository;
import com.staff.entity.Staff;

@Service
@Transactional
public class InstituteService implements IInstituteService {
	@Autowired
	private InstituteRepository instituteRepository;
	@Autowired
	private StaffRepository staffDao;
	@Autowired
	private PositionRepository positionDao;
	

	

	public Institute findOne(Long id) {
		return instituteRepository.findOne(id);
	}

	public List<Institute> findAll() {
		return (List<Institute>) instituteRepository.findAll();
	}
	@Transactional(readOnly=true)
	public Page<Institute> findAll(Specification<Institute> spec, Pageable pageable) {
		return instituteRepository.findAll(spec, pageable);
	}
	
	//寻找父节点
	public Institute findFather(Institute institute) {
		return instituteRepository.findOne(institute.getId()).getFather();
	}

	//获取在职员工数
	public Integer getStaffNum(Institute institute) {
		return instituteRepository.findStaffsByDept(institute.getId()).size();
	}



	public Staff getPrinsipal(Institute institute) {
		Institute i = instituteRepository.findOne(institute.getId());
		return i.getPrincipal();
	}

	public Institute findDeptByName(String name) {
		return instituteRepository.findByDeptName(name);
	}

	

	public void saveOrUpdate(InstituteDTO dto) {
		
		Institute father = null;
		if(dto.getFatherId()!=null)father = instituteRepository.findOne(dto.getFatherId());
		Institute i = null;
		if(dto.getDeptId() != null) {
			i = instituteRepository.findOne(dto.getDeptId());
			i.setName(dto.getName());
			i.setCode(dto.getCode());
			i.setCapacity(dto.getCapacity());
		}else {
			i = new Institute(dto,father);
		}
		instituteRepository.save(i);
		
	}

	public void deleteInstitute(Long id) {
		//是否有子部门或职务或List<Staff>
		if(instituteRepository.findStaffsByDept(id).size()>0)return;
		if(instituteRepository.findChildren(id).size()>0)return;
		if(instituteRepository.findPositions(id).size()>0)return;
		Institute i = instituteRepository.findOne(id);
		i.setFather(null);
		instituteRepository.save(i);
		instituteRepository.delete(id);
		
	}

	public boolean hasChildren(Long id) {
		if(instituteRepository.findChildren(id).size()!=0)return true;
		return false;
	}
	
	//合并部门
	public void combineInstitute(Long fatherId, Long childId) {
		//↓合并
		//1 转移员工
		for(Staff staff:instituteRepository.findStaffsByDept(childId)) {
			Institute father = instituteRepository.findOne(fatherId);
			staff.setDepartment(father);
			staffDao.save(staff);
		}
		//2 转移子部门
		for(Institute i:instituteRepository.findChildren(childId)) {
			Institute father = instituteRepository.findOne(fatherId);
			i.setFather(father);
			instituteRepository.save(i);
		}
		//3 转移职务
		for(Position p:instituteRepository.findPositions(childId)) {
			Institute father = instituteRepository.findOne(fatherId);
			p.setDept(father);
			positionDao.save(p);
		}
		
		Institute child = instituteRepository.findOne(childId);
		//去除原父节点关系
		child.setFather(null);
		//去除负责人
		child.setPrincipal(null);
		instituteRepository.save(child);
		instituteRepository.delete(child);
	}
	
	//判断 seachId是否为id的下级部门,遍历以id为根节点的普通树
	public boolean isSubordinateDept(Long id, Long searchId) {
		Institute root = instituteRepository.findOne(id);
		List<Institute> set = instituteRepository.findChildren(id);
		while(set.size()>0) {
			System.out.println("遍历到子节点："+set.get(0).getName());
			Institute i = set.get(0);
			if(i.getId()==searchId)return true;
			set.remove(0);
			List<Institute> subNodes =  instituteRepository.findChildren(i.getId());
			for(Institute subNode:subNodes) {
				set.add(subNode);
			}
		}
		
		return false;
	}

	public void moveInstitute(Long fatherId, Long childId) {
		Institute child = instituteRepository.findOne(childId);
		Institute father = instituteRepository.findOne(fatherId);
		if(father!=null) {
			child.setFather(father);
			child.setLevel(father.getLevel()+1);
			instituteRepository.save(child);
		}
	}

	public boolean hasPositions(Long id) {
		if(instituteRepository.findPositions(id).size()>0)return true;
		return false;
	}

	public boolean hasStaffs(Long id) {
		if(instituteRepository.findStaffsByDept(id).size()>0)return true;
		return false;
	}

	public void selectPrincipal(Long deptId, Long staffId) {
		Institute dept = instituteRepository.findOne(deptId);
		if(dept==null)return;
		if(staffId == null) {
			dept.setPrincipal(null);
			instituteRepository.save(dept);
			return;
		}
		Staff principal = staffDao.findOne(staffId);
		if(!principal.getDepartment().getName().equals(dept.getName()))return;
		dept.setPrincipal(principal);
		instituteRepository.save(dept);
	}

	public Page<PrincipalDTO> findStaffByDept(PrincipalDTO dto,Pageable pageable) {
		Institute dept = instituteRepository.findOne(dto.getDeptId());
		if(dept == null)return null;
		List<PrincipalDTO> results = new ArrayList<PrincipalDTO>();
		Page<Staff> page = staffDao.findAll(PrincipalDTO.getSpecification(dept, dto), pageable);
		for(Staff staff:page.getContent()) {
			results.add(new PrincipalDTO(staff, staff.getDepartment().getId(), staff.getPosition().getName()));
		}
		return new PageImpl<PrincipalDTO>(results,pageable,results.size());
	}

	public List<Institute> findCombineDept(Long id) {
		List<Institute> list = (List<Institute>) instituteRepository.findAll();
		List<Institute> results = new ArrayList<Institute>();
		for(Institute institute:list) {
			if(institute.getId()!=id&&!isSubordinateDept(id, institute.getId()))results.add(institute);
		}
		return results;
	}

	public List<Institute> findMoveDept(Long id) {
		List<Institute> list = (List<Institute>) instituteRepository.findAll();
		List<Institute> results = new ArrayList<Institute>();
		Institute dept = instituteRepository.findOne(id);
		Long fatherId = null;
		if(dept.getFather()!=null)fatherId = dept.getFather().getId();
		for(Institute institute:list) {
			if(institute.getId()!=fatherId&&institute.getId()!=id&&!isSubordinateDept(id, institute.getId()))
				results.add(institute);
		}
		return results;
	}

	public boolean isNameExist(InstituteDTO dto) {
		List<Institute> list = (List<Institute>) instituteRepository.findAll();
		for(Institute i:list) {
			if(i.getId()!=dto.getDeptId()&&i.getName().equals(dto.getName()))return true;
		}
		return false;
	}

	public boolean isCodeExist(InstituteDTO dto) {
		List<Institute> list = (List<Institute>) instituteRepository.findAll();
		for(Institute i:list) {
			if(i.getId()!=dto.getDeptId()&&i.getCode().equals(dto.getCode()))return true;
		}
		return false;
	}

	public boolean isPrincipal(Long staffId) {
		Institute i = instituteRepository.findByPrincipal(staffId);
		if(i!=null)return true;
		return false;
	}
	//查找返回部门树形结构
	public TreeNode<InstituteDTO> findTree() {
		//要返回的树：tree
		TreeNode<InstituteDTO> tree = new TreeNode<InstituteDTO>();
		List<Institute> roots = (List<Institute>) instituteRepository.findRootInstitutes();
		List<InstituteDTO> rootDTOs = new ArrayList<InstituteDTO>();
		
		for(Institute root:roots) {
			InstituteDTO rootDTO = findChildTree(root.getId());
			tree.getChildren().add(rootDTO);
		}
		
		return tree;
	}
	public InstituteDTO findChildTree(Long id){
		Institute root = instituteRepository.findOne(id);
		if(root == null)return null;
		
		Integer stuffNum = instituteRepository.findStaffsByDept(id).size();
		String principal = null;
		if(root.getPrincipal()!=null)principal = root.getPrincipal().getStaffName();
		InstituteDTO rootDTO = new InstituteDTO(root, stuffNum, principal, root.getId());
		
		List<Institute> nodes = instituteRepository.findChildren(id);
		for(Institute node:nodes) {
			InstituteDTO child = findChildTree(node.getId());
			rootDTO.getChildren().add(child);
		}
		return rootDTO;
	}

}
